//
//  NodePool.cpp
//  client
//
//  Created by will on 24/01/2018.
//

#include "NodePool.hpp"
#include "cocos2d.h"

static NodePool* _instance = nullptr;

NodePool* NodePool::getInstance()
{
    if (!_instance)
    {
        _instance =  new (std::nothrow) NodePool();
    }
    return _instance;
}
void NodePool::destroyInstance()
{
    if (_instance != nullptr)
    {
        delete _instance;
        _instance = nullptr;
    }
}

NodePool::~NodePool()
{
    clear();
}

void NodePool::put(cocos2d::Node* node)
{
    if (node != nullptr)
    {
        std::string key = typeid(*node).name();
        put(node, key);
    }
}

void NodePool::put(cocos2d::Node* node, const std::string& key)
{
    if (node != nullptr)
    {
        NodeList& deque = _pool[key];
        deque.push(node);
        node->retain();
    }
}

cocos2d::Node* NodePool::getByKey(const std::string& key)
{
    cocos2d::Node* ret = nullptr;
    NodeList& deque = _pool[key];
    if (deque.size() > 0)
    {
        ret = deque.front();
        deque.pop();
        ret->autorelease();
    }
    return ret;
}

template<typename T>
bool NodePool::get(T& t)
{
    std::string key = typeid(t).name();
    cocos2d::Node* node = getByKey(key);
    if (node)
    {
        t = dynamic_cast<T>(*node);
    }
        
    return node != nullptr;
}

size_t NodePool::size(const std::string& key) const
{
    auto it = _pool.find(key);
    if (it != _pool.end())
    {
        return it->second.size();
    }
    return 0;
}

void NodePool::clear()
{
    for(auto q : _pool)
    {
        auto& queue = q.second;
        while(queue.size()>0)
        {
            queue.front()->cleanup();
            queue.front()->release();
            queue.pop();
        }
    }
    _pool.clear();
}
